package Simulation;

import java.io.BufferedReader;
import java.io.FileReader;
import java.util.StringTokenizer;
import java.util.Vector;

import fxana.FxRawDataSet;
import fxana.RawDataCell;

public class ConditionEx extends Condition {

	static Vector <RawDataCell> externcond=null;
	static Vector <String> ExternCmdTable=new Vector<String>(); 
	static String [] DefaultExternCmdTable={
			"/home/joukan/bin/getextern.m"
	};
	
	
	static{
		/* Set the default ExternCmdTable */
		int i;
		for(i=0;i<DefaultExternCmdTable.length;i++){
			ExternCmdTable.add(DefaultExternCmdTable[i]);
		}
	}
	
	public ConditionEx() {
		// TODO Auto-generated constructor stub
	}

	public ConditionEx(FxRawDataSet ds, RawDataCell today,
			EvaluatorParaFlag flag) {
		super(ds, today, flag);
	}

	@Override
	protected void PreProcess(FxRawDataSet ds, RawDataCell today,
			EvaluatorParaFlag flag) {
		
		if(ConditionEx.externcond==null){
			if(!this.DoExternCmd(flag)){
				super.State=ConditionState.BAD;
				return;
			}
		
			if(!this.LoadExtern()){
				super.State=ConditionState.BAD;
				return;
			}
		}
		
		if(flag.IsLFlagSet()&&flag.GetLFlagIterator().hasNext()){
			super.LossCutValue=flag.GetLFlagIterator().next()/10.0;
		}

	}

	@Override
	protected Condition GetNew(FxRawDataSet ds, RawDataCell today,
			EvaluatorParaFlag flag) {
		return new ConditionEx(ds,today,flag);
	}

	@Override
	protected RawDataCell GetEstimatedValue(FxRawDataSet ds, RawDataCell today,
			EvaluatorParaFlag flag) {
		
		if(ConditionEx.externcond==null){
			if(!this.DoExternCmd(flag)){
				super.State=ConditionState.BAD;
				return null;
			}
			
			if(!this.LoadExtern()){
				super.State=ConditionState.BAD;
				return null;
			}
		}
		
		Double losscut;
		if(flag.IsLFlagSet()&&flag.GetLFlagIterator().hasNext()){
			losscut=flag.GetLFlagIterator().next()/10.0;
			if((this.LossCutValue.compareTo(1.0)==0)&&(this.LossCutValue.compareTo(losscut)!=0)){
				this.LossCutValue=losscut;
			}
		}
		
		int i;
		for(i=0;i<ConditionEx.externcond.size();i++){
			if(ConditionEx.externcond.elementAt(i).GetRecDate().compareTo(today.GetRecDate())==0){
				return ConditionEx.externcond.elementAt(i);
			}
		}
		
		return null;
	}
	
	public static void ResetExternCondition(){
		ConditionEx.externcond=null;
		
	}
	
	protected String GetParameter(EvaluatorParaFlag flag){
		String parameter=null;
		int cmdindex=0;
		if(flag.IsCFlagSet()&&flag.GetCFlagIterator().hasNext()){
			cmdindex=flag.GetCFlagIterator().next();
		}
		switch(cmdindex){
		case 0: /*getextern.m*/
			Integer numberofday=25;
			Integer order=1;
			if(flag.IsMFlagSet()&&flag.GetMFlagIterator().hasNext()){
				numberofday=flag.GetMFlagIterator().next();
			}
			
			if(flag.IsDFlagSet()&&flag.GetDFlagIterator().hasNext()){
				order=flag.GetDFlagIterator().next();
			}
			
			parameter=numberofday.toString()+" "+order.toString();
			break;
		default: /* for custom cmd use flag.option as parameter */
			parameter=flag.option;
		}
		return parameter;
	}
	public  boolean DoExternCmd(EvaluatorParaFlag flag){
		
		int cmdindex=0;
		if(flag.IsCFlagSet()&&flag.GetCFlagIterator().hasNext()){
			cmdindex=flag.GetCFlagIterator().next();
		}
		if(cmdindex>=ConditionEx.ExternCmdTable.size()){
			System.err.println("Extern command index "+cmdindex+" is wrong!");
			return false;
		}
		
		try {
				System.err.println("Run "+ConditionEx.ExternCmdTable.elementAt(cmdindex)+" "+GetParameter(flag)+".");
				Process process=Runtime.getRuntime().exec(ConditionEx.ExternCmdTable.elementAt(cmdindex)+" "+ GetParameter(flag) );
				process.waitFor();
				
		} catch(Exception e) {
				System.err.println("Failed to run "+ConditionEx.ExternCmdTable.elementAt(cmdindex)+" "+GetParameter(flag) +".");
				return false;
		}
		return true;
	}
	
	public static Integer RegisterExternCmd(String externcmd){
		ConditionEx.ExternCmdTable.add(externcmd);
		return ConditionEx.ExternCmdTable.size()-1;
	}
	public static boolean UnRegisterExternCmd(Integer cmdindex){
		if(cmdindex<ConditionEx.DefaultExternCmdTable.length){
			System.err.println("Can not unregiser default extern cmd.");
			return false;
		}
		
		if(cmdindex>=ConditionEx.ExternCmdTable.size()){
			System.err.println("Extern command index "+ cmdindex+" is outof bound.");
			return false;
		}
		ConditionEx.ExternCmdTable.remove(cmdindex);
		return true;
	}
	protected boolean LoadExtern(){
		String aLine=null;		
		
		if(ConditionEx.externcond!=null){
			/*Remove the old data*/
			ConditionEx.externcond.clear();
		}else{
			ConditionEx.externcond=new Vector<RawDataCell>();
		}
		/*Set the file name*/
		String filename="/home/joukan/data/result.csv";		
		try{
			BufferedReader fin=new BufferedReader(new FileReader(filename));
			while((aLine=fin.readLine())!=null){
				StringTokenizer tokenLine= new StringTokenizer(aLine,",");
				String date=new String(tokenLine.nextToken());				
				Double  highv=new Double(tokenLine.nextToken());
				Double  lowv=new Double(tokenLine.nextToken());
				RawDataCell newcell= new RawDataCell(date,null,highv,lowv,null);
				if(highv.compareTo(lowv)>=0){
					ConditionEx.externcond.add(newcell);
				}else{
					System.err.print("Wrong data:"+newcell.GetRecDate()+"\n");
					return false;
				}
			}
			fin.close();
		}catch(Exception e){			
			return false;			
		}		
		return true;
	}

	@Override
	protected void UpdateLossCutValue(FxRawDataSet ds, RawDataCell today,
			EvaluatorParaFlag flag) {
		return;
	}

}
